﻿using AutoMapper;
using Hotel.Application.Admins.Dto;
using Hotel.Domain;
using Hotel.Repositories;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Hotel.Application
{
    //[LogInterceptor]
    public class BaseService<TEntity, TCreateUpdateDto, TListDto> : IBaseService<TEntity, TCreateUpdateDto, TListDto> 
        where TEntity : class, new()
        where TCreateUpdateDto : class, new()
        where TListDto : class, new()
    {
        private readonly IRepository<TEntity> repository;

        /// <summary>
        /// 缓存类属性注入
        /// </summary>
        public IDistributedCache<TListDto> cache { get; set; }

        /// <summary>
        /// AutoMapper属性注入
        /// </summary>
        public IMapper mapper { get; set; }

        public BaseService(IRepository<TEntity> repository)
        {
            this.repository = repository;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<long> InsertAsync(TCreateUpdateDto dto)
        {
            return await repository.InsertAsync(mapper.Map<TEntity>(dto));
        }

        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual async Task<List<long>> ManyInsertAsync(List<TCreateUpdateDto> dtos)
        {
            return await repository.ManyInsertAsync(mapper.Map<List<TEntity>>(dtos));
        }

        /// <summary>
        /// 单条删除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual async Task<int> DeleteAsync(long key)
        {
            return await repository.DeleteAsync(key);
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual async Task<int> ManyDeleteAsync(List<long> keys)
        {
            return await repository.ManyDeleteAsync(keys);
        }

        /// <summary>
        /// 单条更新
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsyc(TCreateUpdateDto dto)
        {
            return await repository.UpdateAsyc(mapper.Map<TEntity>(dto));
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual async Task<int> ManyUpdateAsyc(List<TCreateUpdateDto> dtos)
        {
            return await repository.ManyUpdateAsyc(mapper.Map<List<TEntity>>(dtos));
        }

        /// <summary>
        /// 更新某些字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns">要更新的字段</param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsyc(TCreateUpdateDto dto, string columns)
        {
            return await repository.UpdateAsyc(mapper.Map<TEntity>(dto), columns);
        }

        /// <summary>
        /// 查全部
        /// </summary>
        /// <returns></returns>
        public virtual async Task<ResultDto<List<TListDto>>> QueryAsync()
        {
            var list = await cache.GetOrAddAsync(typeof(TEntity).Name, async () =>
            {
                return mapper.Map<List<TEntity>, List<TListDto>>(await repository.QueryAsync());
            });
            
            return new ResultDto<List<TListDto>> {
                code = State.Success,
                count = list.Count,
                data = mapper.Map<List<TListDto>>(list)
            };
        }

        /// <summary>
        /// 按条件查询
        /// </summary>
        /// <returns></returns>
        public virtual async Task<List<TListDto>> QueryAsync(Expression<Func<TEntity, bool>> expression)
        {
            var list = await repository.QueryAsync(expression);
            return mapper.Map<List<TListDto>>(list);
        }

        /// <summary>
        /// 查单条
        /// </summary>
        /// <returns></returns>
        public virtual async Task<TListDto> FindAsync(long key)
        {
            var entity = await repository.FindAsync(key);
            return mapper.Map<TListDto>(entity);
        }

        /// <summary>
        /// 异步分页
        /// </summary>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <returns></returns>
        public virtual async Task<ResultDto<List<TListDto>>> ToPageListAsync(int PageSize = 10, int PageIndex = 1)
        {
            var pageData = await repository.ToPageListAsync(PageSize, PageIndex);
            var list = mapper.Map<List<TListDto>>(pageData.Item1);
            return new ResultDto<List<TListDto>> {
                code = State.Success,
                data = list,
                count = pageData.Item2
            };
        }

        /// <summary>
        /// 异步分页
        /// </summary>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <returns></returns>
        public virtual async Task<ResultDto<List<TListDto>>> ToPageListAsync(Expressionable<TEntity> expressionable, int PageSize = 10, int PageIndex = 1)
        {
            var pageData = await repository.ToPageListAsync(expressionable.ToExpression(), PageSize, PageIndex);
            var list = mapper.Map<List<TListDto>>(pageData.Item1);
            return new ResultDto<List<TListDto>>
            {
                code = State.Success,
                data = list,
                count = pageData.Item2
            };
        }

        /// <summary>
        /// 异步分页
        /// </summary>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <returns></returns>
        public virtual async Task<ResultDto<List<TListDto>>> ToPageListAsync(Expression<Func<TEntity, object>> sort, Expressionable<TEntity> expressionable, int PageSize = 10, int PageIndex = 1)
        {
            var pageData = await repository.ToPageListAsync(sort, expressionable.ToExpression(), PageSize, PageIndex);
            var list = mapper.Map<List<TListDto>>(pageData.Item1);
            return new ResultDto<List<TListDto>>
            {
                code = State.Success,
                data = list,
                count = pageData.Item2
            };
        }

        /// <summary>
        /// 同步分页
        /// </summary>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <returns></returns>
        public virtual ResultDto<List<TListDto>> ToPageList(int PageSize = 10, int PageIndex = 1)
        {
            var pageData = repository.ToPageList(PageSize, PageIndex);
            var list = mapper.Map<List<TListDto>>(pageData.Item1);
            return new ResultDto<List<TListDto>> {
                code = State.Success,
                data = list,
                count = pageData.Item2
            };
        }

        /// <summary>
        /// 同步分页
        /// </summary>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <returns></returns>
        public virtual ResultDto<List<TListDto>> ToPageList(Expressionable<TEntity> expressionable, int PageSize = 10, int PageIndex = 1)
        {
            var pageData = repository.ToPageList(expressionable.ToExpression(), PageSize, PageIndex);
            var list = mapper.Map<List<TListDto>>(pageData.Item1);
            return new ResultDto<List<TListDto>>
            {
                code = State.Success,
                data = list,
                count = pageData.Item2
            };
        }

        /// <summary>
        /// 根据实体批量删除
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public async Task<int> ManyDeleteAsync(List<TEntity> entities)
        {
            return await repository.DeleteAsync(entities);
        }
    }
}
